package com.xm.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xm.common.utils.StrPool;
import com.xm.web.consts.MagicNumEnum;
import com.xm.web.entity.po.TbPermission;
import com.xm.web.entity.po.TbRole;
import com.xm.web.entity.request.RolePermissionRequest;
import com.xm.web.entity.request.RoleRequest;
import com.xm.web.entity.response.RoleResponse;
import com.xm.web.mapper.TbRoleMapper;
import com.xm.web.service.ITbPermissionService;
import com.xm.web.service.ITbRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xm.web.utils.PermissionTreeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author yousj
 * @since 2021-08-18
 */
@Service
@RequiredArgsConstructor
public class TbRoleServiceImpl extends ServiceImpl<TbRoleMapper, TbRole> implements ITbRoleService {

    @Value("${role.default.permissions}")
    private String roleDefaultPermissions;

    private final ITbPermissionService permissionService;

    public List<String> selectRulesByUser(String username) {
        return baseMapper.selectRulesByUser(username);
    }

    public List<TbRole> list(String roleName) {
        return list(Wrappers.<TbRole>lambdaQuery().like(Objects.nonNull(roleName), TbRole::getRoleName, roleName)).stream().filter(r -> !r.getRules().contains(StrPool.NEGATIVE)).collect(Collectors.toList());
    }

    @Override
    public RoleResponse getById(Integer id) {
        RoleResponse response = BeanUtil.copyProperties(baseMapper.selectById(id), RoleResponse.class);
        List<Integer> rules = Arrays.stream(response.getRules().split(",")).map(Integer::valueOf).collect(Collectors.toList());
        List<TbPermission> permissions = permissionService.list(Wrappers.<TbPermission>lambdaQuery()
                .eq(TbPermission::getStatus, MagicNumEnum.ON.getCode())
                .in(!rules.contains(MagicNumEnum.ROOT.getCode()), TbPermission::getId, rules));
        List<Tree<Integer>> trees = PermissionTreeUtil.permissions2tree(permissions);
        List<Integer> allEndRules = new ArrayList<>();
        PermissionTreeUtil.getAllEndRules(trees, allEndRules);
        response.setAllEndRules(allEndRules);
        return response;
    }

    @Override
    public boolean add(RoleRequest request) {
        TbRole role = BeanUtil.copyProperties(request, TbRole.class);
        role.setRules(roleDefaultPermissions);
        return save(role);
    }

    @Override
    public boolean update(RoleRequest request) {
        TbRole role = BeanUtil.copyProperties(request, TbRole.class);
        return updateById(role);
    }

    @Override
    public boolean updatePermissions(RolePermissionRequest request) {
        List<Integer> rules = request.getRules();
        List<Tree<Integer>> trees = permissionService.all();
        List<Integer> allParentMenuIds = new ArrayList<>();
        rules.forEach(r -> PermissionTreeUtil.getAllParentMenuIds(trees, r, allParentMenuIds));
        rules.addAll(allParentMenuIds);
        return update(Wrappers.<TbRole>lambdaUpdate()
                .set(TbRole::getRules, rules.stream().distinct().sorted().map(String::valueOf).collect(Collectors.joining(",")))
                .eq(TbRole::getId, request.getId()));
    }

}
